﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;

namespace TiebaSpider
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private App application;
        private string targetForumName = string.Empty;
        private Beans.ProxyHistoryForum historyData;
        private Beans.ForumInformation forumCache;
        private Beans.ThreadInformation threadCache;
		private Beans.ProxyPartition partitionData;
        private List<string> selectedImageIDs;
        private Beans.DownloadTask downTask;
        private Core.DownloadEngine engine;

        private const string TotalPageDisplay = "共 {0} 页";
        private const string ForumPageAnalysisString = "捕获贴吧第{0}页帖子列表";
        private const string ThreadPageTrackingString = "捕获帖子第{0}页图片，共{1}页";
        private const string ThreadTotalImageString = "帖子图片共{0}张";
        private const string ImageSelectedString = "选中图片{0}张";
        private const string ImageTrackingString = "追踪链接 (第{2}批：{0}/{1})";
        private const string ImageDownloadString = "下载图片 (第{2}批：{0}/{1})";
        private const string DirectoryExists = "帖子内容已下载过";
        private const string DirectoryUnexists = "帖子内容未下载过";

        public MainWindow()
        {
            InitializeComponent();

            forumCache = new Beans.ForumInformation();
            selectedImageIDs = new List<string>();
            application = App.Current as App;

            authorOnly.IsChecked = application.SetupController.UserLastBehavier.OnlySeeOwner;
			partition.IsChecked = true;

            historyData = new Beans.ProxyHistoryForum(application.SetupController);
            forumName.ItemsSource = historyData.History;

			partitionData = new Beans.ProxyPartition();
			partitionList.ItemsSource = partitionData.Partitions;
        }

        private void showOption_MouseEnter(object sender, MouseEventArgs e)
        {
            optionBorder.BorderBrush = new SolidColorBrush(Colors.Lime);
        }

        private void showOption_MouseLeave(object sender, MouseEventArgs e)
        {
            optionBorder.BorderBrush = null;
        }

        private void showOption_MouseDown(object sender, MouseButtonEventArgs e)
        {
            optionBorder.BorderBrush = new SolidColorBrush(Colors.Magenta);
        }

        private void showOption_MouseUp(object sender, MouseButtonEventArgs e)
        {
            optionBorder.BorderBrush = null;

            setup setupWindow = new setup();
            setupWindow.Owner = this;
            setupWindow.Show();
        }

        private void loadForum_Click(object sender, RoutedEventArgs e)
        {
            targetForumName = forumName.Text;
            downloadExists.Text = string.Empty;
            if (!historyData.HasForum(targetForumName))
            {
                historyData.AddHistory(targetForumName);
            }
            spiderStatus.Text = string.Format(ForumPageAnalysisString, 1);
            requestPage.Text = "1";
            requestingIcon.Visibility = Visibility.Visible;
            Core.ForumAnalysiser forumAnalysis = new Core.ForumAnalysiser(historyData.GetForum(targetForumName));
            forumAnalysis.AnalysisComplete += OnForumAnalysisComplete;
            try
            {
                forumAnalysis.RequestThreads(1);
            }
            catch (Core.RetreivingCanceledException rce)
            {
                spiderStatus.Text = "捕获超时，请重试";
            }
        }

        private void OnForumAnalysisComplete(object sender, Core.ForumAnalysiserEventArgs e)
        {
            forumCache = e.ForumInfo;
            threadList.ItemsSource = forumCache.ThreadCache;
            if(threadList.Items.Count>0)
                threadList.ScrollIntoView(threadList.Items[0]);
            maxPages.Content = string.Format(TotalPageDisplay, forumCache.TotalPages);
            requestingIcon.Visibility = Visibility.Hidden;
        }

        private void loadThreads_Click(object sender, RoutedEventArgs e)
        {
            if (targetForumName.Equals(string.Empty))
            {
                MessageBox.Show("请先捕捉贴吧信息。");
                return;
            }
            downloadExists.Text = string.Empty;
            requestingIcon.Visibility = Visibility.Visible;
            Core.ForumAnalysiser forumAnalysis = new Core.ForumAnalysiser(historyData.GetForum(targetForumName));
            forumAnalysis.AnalysisComplete += OnForumAnalysisComplete;
            int reqPage = int.Parse(requestPage.Text ?? "1");
            spiderStatus.Text = string.Format(ForumPageAnalysisString, reqPage);
            try
            {
                forumAnalysis.RequestThreads(reqPage);
            }
            catch (Core.RetreivingCanceledException rce)
            {
                spiderStatus.Text = "捕获超时，请重试";
            }
        }

        private void OnThreadAnalysisComplete(object sender, Core.ThreadAnalysiserEventArgs e)
        {
            requestingIcon.Visibility = Visibility.Hidden;
            threadCache = e.ThreadInfo;
            imageView.ItemsSource = threadCache.ThreadImages;
            if(imageView.Items.Count>0)
                imageView.ScrollIntoView(imageView.Items[0]);
            spiderStatus.Text = string.Format(ThreadTotalImageString, threadCache.ThreadImages.Count);
        }

		private void OnThreadPagePartitionComplete(object sender, Core.ThreadAnalysiserEventArgs e)
		{
			partitionData.LoadPartition(e.ThreadInfo.PagePartition);
			partitionList.SelectedIndex = 0;
		}

        private void probeThread_Click(object sender, RoutedEventArgs e)
        {
            if (threadList.SelectedValue == null)
            {
                MessageBox.Show("请先选择一个帖子。");
                return;
            }
            requestingIcon.Visibility = Visibility.Visible;
            Core.ThreadAnalysiser threadAnalysis = new Core.ThreadAnalysiser(
				threadList.SelectedValue.ToString(), 
				authorOnly.IsChecked ?? false,
				partition.IsChecked ?? false);
            threadAnalysis.AnalysisComplete += OnThreadAnalysisComplete;
            threadAnalysis.PageAnalysisComplete += OnProbingThread;
			threadAnalysis.PartitionSet += OnThreadPagePartitionComplete;
			if (application.SetupController.AppOptions.HideExists)
			{
				if (application.SetupController.AppOptions.StoreInSubdirectory)
				{
					threadAnalysis.DownloadDirectory = application.SetupController.AppOptions.StorageDirectory +
						System.IO.Path.DirectorySeparatorChar +
						historyData.GetForum(targetForumName).Name +
						System.IO.Path.DirectorySeparatorChar +
						((Beans.ForumThread)threadList.SelectedItem).Name;
				}
				else
				{
					threadAnalysis.DownloadDirectory = application.SetupController.AppOptions.StorageDirectory +
						System.IO.Path.DirectorySeparatorChar +
						((Beans.ForumThread)threadList.SelectedItem).Name;
				}
			}
			else
			{
				threadAnalysis.DownloadDirectory = "";
			}
			partitionData.ClearAll();
            spiderStatus.Text = string.Format(ThreadPageTrackingString, 1, "-");
            selectedImageIDs.Clear();
            try
            {
                threadAnalysis.ThreadCapture();
            }
            catch (Core.RetreivingCanceledException rce)
            {
                spiderStatus.Text = "捕获超时，请重试";
            }
        }

        private void OnProbingThread(object sender, Core.ThreadAnalysiserEventArgs e)
        {
			if (partition.IsChecked ?? false)
			{
				if (e.ThreadInfo.ReqPage < e.ThreadInfo.currentPartition.Item2)
				{
					spiderStatus.Text = string.Format(ThreadPageTrackingString, 
						e.ThreadInfo.ReqPage, 
						e.ThreadInfo.currentPartition.Item2 - e.ThreadInfo.currentPartition.Item1 + 1);
				}
			}
			else
			{
				if (e.ThreadInfo.ReqPage < e.ThreadInfo.TotalPage)
				{
					spiderStatus.Text = string.Format(ThreadPageTrackingString, e.ThreadInfo.ReqPage, e.ThreadInfo.TotalPage);
				}
			}
        }

        private void OnImageChecked(object sender, RoutedEventArgs e)
        {
            string tag = ((FrameworkElement)sender).Tag as string;
            if (tag != null)
            {
                selectedImageIDs.Add(tag);
                spiderStatus.Text = string.Format(ImageSelectedString, selectedImageIDs.Count);
            }
            e.Handled = true;
        }

        private void OnImageUnchecked(object sender, RoutedEventArgs e)
        {
            string tag = ((FrameworkElement)sender).Tag as string;
            if (tag != null)
            {
                selectedImageIDs.Remove(tag);
                spiderStatus.Text = string.Format(ImageSelectedString, selectedImageIDs.Count);
            }
            e.Handled = true;
        }

        private void savePics_Click(object sender, RoutedEventArgs e)
        {
            if (selectedImageIDs.Count == 0)
            {
                MessageBox.Show("请先选择一些图片。");
                return;
            }

            downTask = new Beans.DownloadTask();
            downTask.CreateSubDir = application.SetupController.AppOptions.StoreInSubdirectory;
            downTask.TargetDir = application.SetupController.AppOptions.StorageDirectory;
            downTask.ForumName = historyData.GetForum(targetForumName).Name;
            downTask.ForumEncodedName = historyData.GetForum(targetForumName).EncodeName;
            downTask.ThreadID = threadList.SelectedValue.ToString();
            downTask.ThreadName = ((Beans.ForumThread)threadList.SelectedItem).Name;
            downTask.SelectedImageID = selectedImageIDs;
            downTask.BatchSize = application.SetupController.AppOptions.TaskBatchSize;

            eventProgress.Value = 0;
            eventProgress.Maximum = downTask.SelectedImageID.Count * 2;

            engine = new Core.DownloadEngine(downTask);
            engine.StartTrack += OnStartTracking;
            engine.StartDownload += OnStartDownload;
            engine.TrackComplete += OnTrackingProgress;
            engine.DownloadComplete += OnDownloadProgress;
            engine.TaskComplete += OnDownloadComplete;
            engine.StartTask();

            requestingIcon.Visibility = Visibility.Visible;
        }

        private void OnStartTracking(object sender, EventArgs e)
        {
            eventProgress.Value = 0;
            spiderStatus.Text = string.Format(ImageTrackingString, 1, engine.BCEventArgs.BatchSize, engine.Task.DeployedBatch);
        }

        private void OnStartDownload(object sender, EventArgs e)
        {
            eventProgress.Value = 0;
            spiderStatus.Text = string.Format(ImageDownloadString, 1, engine.BCEventArgs.BatchSize, engine.Task.DeployedBatch);
        }

        private void OnTrackingProgress(object sender, Core.TrackEventArgs e)
        {
            if (engine.BCEventArgs.SuccessTracking + engine.BCEventArgs.FailureTracking < engine.BCEventArgs.BatchSize)
                spiderStatus.Text = string.Format(ImageTrackingString, engine.BCEventArgs.SuccessTracking + engine.BCEventArgs.FailureTracking + 1, engine.BCEventArgs.BatchSize, engine.Task.DeployedBatch);
            eventProgress.Value = engine.DCEventArgs.SuccessTracking + engine.DCEventArgs.FailureTracking + engine.DCEventArgs.SuccessDownload + engine.DCEventArgs.FailureDownload;
            failureDownload.Text = string.Format("{0}", engine.DCEventArgs.FailureTracking);
        }

        private void OnDownloadProgress(object sender, Core.DownloadEventArgs e)
        {
            if (engine.BCEventArgs.SuccessDownload + engine.BCEventArgs.FailureDownload < engine.BCEventArgs.BatchSize)
                spiderStatus.Text = string.Format(ImageDownloadString, engine.BCEventArgs.SuccessDownload + engine.BCEventArgs.FailureDownload + 1, engine.BCEventArgs.BatchSize, engine.Task.DeployedBatch);
            eventProgress.Value = engine.DCEventArgs.SuccessDownload + engine.DCEventArgs.FailureDownload + engine.DCEventArgs.SuccessTracking + engine.DCEventArgs.FailureTracking;
            failureDownload.Text = string.Format("{0}", engine.DCEventArgs.FailureDownload + engine.DCEventArgs.FailureTracking);
            successDownload.Text = string.Format("{0}", engine.DCEventArgs.SuccessDownload);
        }

        private void OnDownloadComplete(object sender, Core.DownloadCompleteEventArgs e)
        {
            requestingIcon.Visibility = Visibility.Hidden;
            Directory.SetCurrentDirectory(application.SetupController.AppOptions.StorageDirectory);
            selectedImageIDs.Clear();
            checkAll.IsChecked = false;

            StringBuilder downloadResult = new StringBuilder();
            downloadResult.AppendLine(string.Format("{0}张图片下载成功。", e.SuccessDownload));
            downloadResult.AppendLine(string.Format("{0}张图片下载失败。", e.FailureDownload + e.FailureTracking));
            MessageBox.Show(downloadResult.ToString());
            downloadExists.Text = Core.DownloadEngine.CheckDownloaded(((Beans.ForumThread)threadList.SelectedItem).Name,
                application.SetupController.AppOptions.StorageDirectory,
                historyData.GetForum(targetForumName).Name,
                application.SetupController.AppOptions.StoreInSubdirectory) ? DirectoryExists : DirectoryUnexists;
        }

        private void threadList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            imageView.ItemsSource = null;
            eventProgress.Value = 0;
            spiderStatus.Text = string.Empty;
            successDownload.Text = "0";
            failureDownload.Text = "0";
            checkAll.IsChecked = false;
			partitionData.ClearAll();
            try
            {
                downloadExists.Text = Core.DownloadEngine.CheckDownloaded(((Beans.ForumThread)threadList.SelectedItem).Name,
                    application.SetupController.AppOptions.StorageDirectory,
                    historyData.GetForum(targetForumName).Name,
                    application.SetupController.AppOptions.StoreInSubdirectory) ? DirectoryExists : DirectoryUnexists;
            }
            catch (NullReferenceException nre)
            {
                downloadExists.Text = string.Empty;
            }
        }

        private void prevPage_MouseUp(object sender, MouseButtonEventArgs e)
        {
            int nowPage = int.Parse(requestPage.Text);
            int reqPage = (nowPage - 1) > 0 ? (nowPage - 1) : 1;
            requestPage.Text = reqPage.ToString();
            loadThreads_Click(null, null);
        }

        private void nextPage_MouseUp(object sender, MouseButtonEventArgs e)
        {
            int nowPage = int.Parse(requestPage.Text);
            int reqPage = (nowPage + 1) <= forumCache.TotalPages ? (nowPage + 1) : 1;
            requestPage.Text = reqPage.ToString();
            loadThreads_Click(null, null);
        }

		private void partition_Checked(object sender, RoutedEventArgs e)
		{
			partitionList.IsEnabled = true;
			loadPartition.IsEnabled = true;
		}

		private void partition_Unchecked(object sender, RoutedEventArgs e)
		{
			partitionList.IsEnabled = false;
			loadPartition.IsEnabled = false;
		}

		private void loadPartition_Click(object sender, RoutedEventArgs e)
		{
			String selectKey = partitionList.Text;
			if (partitionData.HasRange(selectKey))
			{
				Tuple<int, int> selectRange = partitionData.FindRange(selectKey);
				if (threadList.SelectedValue == null)
				{
					MessageBox.Show("请先选择一个帖子。");
					return;
				}
				requestingIcon.Visibility = Visibility.Visible;
				Core.ThreadAnalysiser threadAnalysis = new Core.ThreadAnalysiser(
					threadList.SelectedValue.ToString(), 
					authorOnly.IsChecked ?? false,
					partition.IsChecked ?? false,
					selectRange);
				threadAnalysis.AnalysisComplete += OnThreadAnalysisComplete;
				threadAnalysis.PageAnalysisComplete += OnProbingThread;
				threadAnalysis.PartitionSet += OnThreadPagePartitionComplete;
				if (application.SetupController.AppOptions.HideExists)
				{
					if (application.SetupController.AppOptions.StoreInSubdirectory)
					{
						threadAnalysis.DownloadDirectory = application.SetupController.AppOptions.StorageDirectory +
							System.IO.Path.DirectorySeparatorChar +
							historyData.GetForum(targetForumName).Name +
							System.IO.Path.DirectorySeparatorChar +
							((Beans.ForumThread)threadList.SelectedItem).Name;
					}
					else
					{
						threadAnalysis.DownloadDirectory = application.SetupController.AppOptions.StorageDirectory +
							System.IO.Path.DirectorySeparatorChar +
							((Beans.ForumThread)threadList.SelectedItem).Name;
					}
				}
				else
				{
					threadAnalysis.DownloadDirectory = "";
				}
				imageView.ItemsSource = null;
				eventProgress.Value = 0;
				successDownload.Text = "0";
				failureDownload.Text = "0";
				checkAll.IsChecked = false;
				spiderStatus.Text = string.Format(ThreadPageTrackingString, 
					selectRange.Item1, 
					selectRange.Item2 - selectRange.Item1 + 1);
				selectedImageIDs.Clear();
				try
				{
					threadAnalysis.ThreadCapture();
				}
				catch (Core.RetreivingCanceledException rce)
				{
					spiderStatus.Text = "捕获超时，请重试";
				}
			}
			else
			{
				MessageBox.Show("分区信息已过期或已失效。");
			}
		}
    }
}
